﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Oracle.DataAccess.Client;
using System.Data.OleDb;
using System.Data;

namespace GestionCegep.Objects
{
    // Classe qui contient toutes les donnees de l'application
    public class DataStore
    {
        private OracleConnection currentConnection; // Transaction Oracle
        private MyOracleTransaction currentTransaction; // Transaction Courante (Pour la journalisation)
        private List<Departement> departements;         // Liste des departements
        private List<Enseignant> enseignants;           // Liste des enseignants
        private List<Cours> lesCours;                   // Liste des cours
        private List<Etudiant> etudiants;               // Liste des etudiants
        private List<Inscription> inscriptions;         // Liste des inscriptions

        // Constructeur du magasin de donnees
        public DataStore(string connectionString)
        {
            try
            {
                this.currentConnection = new OracleConnection(connectionString);
                departements = Departement.GetDepartementsFromDataBase(currentConnection);
                enseignants = Enseignant.GetEnseignantsFromDataBase(currentConnection, departements);
                lesCours = Cours.GetCoursFromDataBase(currentConnection, enseignants, departements);
                etudiants = Etudiant.GetEtudiantsFromDataBase(currentConnection);
                inscriptions = Inscription.GetInscriptionsFromDataBase(currentConnection, etudiants, lesCours);
            }
            catch (OracleException exception)
            {
                throw exception;
            }
        }

        public OracleConnection CurrentConnection { get { return currentConnection; } }
        public MyOracleTransaction CurrentTransaction { get { return currentTransaction; } }
        public List<Departement> Departements { get { return departements; } }
        public List<Enseignant> Enseignants { get { return enseignants; } }
        public List<Cours> LesCours { get { return lesCours; } }
        public List<Etudiant> Etudiants { get { return etudiants; } }
        public List<Inscription> Inscriptions { get { return inscriptions; } }

        // Insertion d'un objet dans la base de données
        public void Insert(PersistentObject persistentObject)
        {
            try
            {
                currentConnection.Open(); // Ouverture de la connexion a la base de donnees
                currentTransaction = new MyOracleTransaction(currentConnection.BeginTransaction(), currentConnection); // Transaction courante
                currentTransaction.PushLogToBD(LogActions.Debut, String.Empty); // Journalisation du debut de transaction

                persistentObject.InsertIntoDataBase(currentConnection, this); // Insertion dans la base de données

                currentTransaction.PushLogToBD(LogActions.Confirmer, String.Empty); // Journalisation de confirmation de la transaction

                currentTransaction = null;
                currentConnection.Close();
            }
            catch (OracleException exception)
            {
                currentTransaction.Rollback();
                currentTransaction.PushLogToBD(LogActions.Annuler, String.Empty);
                currentTransaction = null;
                currentConnection.Close();
                throw exception;
            }
        }

        // Verouillage pour la mise a jour d'un objet
        public void LockForUpdate(PersistentObject persistentObject)
        {
            OracleCommand command; // Commande Oracle
            try
            {
                currentConnection.Open(); // Ouverture de la connexion
                currentTransaction = new MyOracleTransaction(currentConnection.BeginTransaction(IsolationLevel.ReadCommitted), currentConnection);

                currentTransaction.PushLogToBD(LogActions.Debut, String.Empty); // Journalisation du debut de transaction

                persistentObject.LockForUpdate(currentConnection); // Vérouillage pour la mise a jour
            }
            catch (OracleException exception)
            {
                currentTransaction.Rollback();
                currentTransaction.PushLogToBD(LogActions.Annuler, String.Empty);
                currentTransaction = null;
                currentConnection.Close();
                throw exception;
            }
        }

        // Confirmation de la mise a jour
        public void CommitUpdate(PersistentObject persistentObject)
        {
            try
            {
                persistentObject.UpdateIntoDataBase(currentTransaction); // Mise a jour dans la base de données
                currentTransaction.PushLogToBD(LogActions.Confirmer, String.Empty); // Journalisation pour la confirmation de la transaction
                currentTransaction = null;
                currentConnection.Close();
            }
            catch (OracleException exception)
            {
                currentTransaction.Rollback(); // Annulation de la transaction
                currentTransaction.PushLogToBD(LogActions.Annuler, String.Empty); // Journalisation pour l'annulation de la transaction
                currentTransaction = null;
                currentConnection.Close();
                throw exception;
            }
        }

        // Annulation de la mise a jour
        public void CancelUpdate()
        {
            try
            {
                // Si la connexion est active, on ferme la connexion
                if (currentConnection.State == ConnectionState.Open)
                {
                    currentTransaction.Rollback();
                    currentTransaction.PushLogToBD(LogActions.Annuler, String.Empty);
                    currentTransaction = null;
                    currentConnection.Close();
                }
            }
            catch (OracleException exception)
            {
                throw exception;
            }
        }
        // Suppression dans la base de données
        public void Delete(PersistentObject persistentObject)
        {
            OracleCommand command; // Commande Oracle
            try
            {
                currentConnection.Open(); // Ouverture de la connexion
                currentTransaction = new MyOracleTransaction(currentConnection.BeginTransaction(), currentConnection); // Transaction courante

                currentTransaction.PushLogToBD(LogActions.Debut, String.Empty); // Journalisation du debut de la transaction

                persistentObject.DeleteFromDataBase(currentConnection,  this); // Suppression ans la base de donnees

                currentTransaction.PushLogToBD(LogActions.Confirmer, String.Empty); // Journalisation de la confirmation de la transaction

                currentTransaction = null;
                currentConnection.Close(); // Fermeture de la connexion
            }
            catch (OracleException exception)
            {
                currentTransaction.Rollback(); // Annulation de la transaction
                currentTransaction = null;
                currentConnection.Close(); // Fermeture de la connexion
                throw exception;
            }
        }
    }
}
